package itheima.service.impl;

import itheima.dao.UserDao;
import itheima.domain.SysRole;
import itheima.domain.SysUser;
import itheima.service.RoleService;
import itheima.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

@Service
@Transactional
public class UserServiceImpl implements UserService {
    @Autowired
    private UserDao userDao;

    @Autowired
    private RoleService roleService;

    private BCryptPasswordEncoder passwordEncoder;

    @Override
    public void save(SysUser user) {
        user.setPassword(passwordEncoder.encode(user.getPassword()));
        userDao.save(user);
    }

    @Override
    public List<SysUser> findAll() {
        return userDao.findAll();
    }

    @Override
    public Map<String, Object> toAddRolePage(Integer id) {
        List<SysRole> allRoles = roleService.findAll();
        List<Integer> myRoles = userDao.findRolesByUid(id);
        Map<String, Object> map = new HashMap<>();
        map.put("allRoles", allRoles);
        map.put("myRoles", myRoles);
        return map;
    }

    @Override
    public void addRoleToUser(Integer userId, Integer[] ids) {
        userDao.removeRoles(userId);
        for (Integer rid : ids) {
            userDao.addRoles(userId, rid);
        }
    }


    /**
     * 认证业务
     * @param username 用户在浏览器中输入的用户名
     * @return UserDetails 是springsecurity自己的用户对象,是框架提供的一个接口，表示用户信息
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //做一步安全判断
        try {
            //根据用户名查询用户信息
            SysUser sysUser = userDao.findByName(username);
            if (sysUser == null){
                //用户名不存在
                return null;
            }
            //Collection<? extends GrantedAuthority> authorities;
            //List<? extends SimpleGrantedAuthority> authorities = new ArrayList<>();
            //根据用户名查询用户所拥有的角色
            List<SimpleGrantedAuthority> authorities = new ArrayList<>();
            List<SysRole> roles = sysUser.getRoles();
            for (SysRole role : roles) {
                authorities.add(new SimpleGrantedAuthority(role.getRoleName()));
            }
            //后续再将下面的改成动态的密码
            authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
            //{noop}后面的密码,springsecurity会认为是原文.
            //根据用户名查询用户所拥有的角色
            //UserDetails userDetails = new User(sysUser.getUsername(),"{noop}"+sysUser.getPassword(),authorities);
            //boolean enabled               是否可用
            //boolean accountNonExpired     账户是否失效
            //boolean credentialsNonExpired 秘密是否失效
            //boolean accountNonLocked      账户是否锁定   四个必须都是true,用户才能正常登录,只用第一个布尔值做个测试，修改认证业务代码
            UserDetails userDetails = new User(sysUser.getUsername(),
                    sysUser.getPassword(),
                    sysUser.getStatus() == 1,
                    true,true,true,
                    authorities);
            return userDetails;
            //还要在springsecurity中把认证数据的来源改了 → spring-security.xml

        }catch (Exception e){
            e.printStackTrace();
            //throw new UsernameNotFoundException("用户名不存在");
            //认证失败
            return null;

        }
    }
}
